package com.cg.asm.license.verify;


import com.cg.asm.license.encryption.XORUtil;
import com.cg.asm.license.holder.LicenseManagerHolder;
import com.cg.asm.license.utils.ServerNetInterfaceUtils;
import de.schlichtherle.license.*;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;
import java.util.prefs.Preferences;

public class LicenseVerify {
    /** 公钥别名 */
    private String pubAlias;
    /** 密钥库访问密码 */
    private String keyStorePwd;
    /** 证书路径 */
    private String licName;
    /** 公钥库路径 */
    private String pubPath;
    /** 系统的统一识别码 */
    private String subject;

    /** 运行环境 */
    private String evn;

    public LicenseVerify(InputStream in) {
        this.setConf(in);
    }

    /**
     * 读取配置文件信息
     */
    private void setConf(InputStream in) {
        Properties prop = new Properties();
        try {
            prop.load(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
        pubAlias = prop.getProperty("public.alias");
        keyStorePwd = prop.getProperty("key.store.pwd");
        licName = prop.getProperty("license.name");
        pubPath = prop.getProperty("public.store.path");
        subject = prop.getProperty("subject");
        evn = prop.getProperty("evn");
    }

    private LicenseParam initLicenseParams() {
        Class<LicenseVerify> clazz = LicenseVerify.class;
        Preferences pre = Preferences.userNodeForPackage(clazz);
        CipherParam cipherParam = new DefaultCipherParam(keyStorePwd);
        KeyStoreParam pubStoreParam = new DefaultKeyStoreParam(
                clazz, pubPath, pubAlias, keyStorePwd, null);
        return new DefaultLicenseParam(subject, pre, pubStoreParam, cipherParam);
    }

    // 获取证书管理器（单例）
    private LicenseManager getLicenseManager() {
        return LicenseManagerHolder.getLicenseManager(initLicenseParams());
    }

    /**
     * 安装证书
     */
    public String install(File file) {
        String resultCode = "success";
        String msg = "-------------------------------------- 证书错误，错误码：";
        try {
            LicenseManager licenseManager = this.getLicenseManager();
            licenseManager.install(file);
        } catch (FileNotFoundException e) { // 未找到证书文件
            resultCode = "1001";
        } catch (LicenseContentException e) {
            resultCode = "1002";
        } catch (Exception e) {
            resultCode = "1003";
            e.printStackTrace();
        }
        // 打印安装信息
        if (!"success".equals(resultCode)) {
            System.out.println(msg + resultCode);
        }
        return resultCode;
    }

    public String getLicName(){
        return licName;
    }
    public static String getConfiPath(){
        return "verify/licenseVerifyConf.properties";
    }

    /**
     * 验证证书信息
     */
    public String verify() {
        String resultCode;
        String msg = "-------------------------------------- 证书错误，错误码：";
        try {
            LicenseManager licenseManager = this.getLicenseManager();
            LicenseContent content = licenseManager.verify();
            resultCode = this.validateExtraInfo(content);
        } catch (NoLicenseInstalledException e) { // 没有安装证书
            resultCode = "1000";
        } catch (LicenseContentException e) { // 证书基本信息验证
            resultCode = "0000";
        } catch (Exception e) { // 其他未知的验证错误
            resultCode = "0001";
            e.printStackTrace();
        }
        // 打印验证信息
        if (!"success".equals(resultCode)) {
            System.out.println(msg + resultCode);
        }
        return resultCode;
    }

    /**
     * 验证证书中的其他信息(Mac地址验证, 开发环境无需验证mac)
     * @param content 证书内容
     * @return 验证结果 success: 验证通过 其他编码: 另见错误信息
     */
    private String validateExtraInfo(LicenseContent content) {
        String valiCode = "success";
        Object extra = content.getExtra();
        if (null != extra) {
            Map extraInfo = (Map) extra;
            String envMark = (String) extraInfo.get("ENV");
            if (null != envMark && envMark.equals(evn)) return "success";
            String macAddress = (String) extraInfo.get("MAC_ADDRESS");
            String ip4Address = (String) extraInfo.get("IP4_ADDRESS");
            if (null == macAddress || "".equals(macAddress)) { // 未设置授权mac地址
                valiCode = "0003";
            } else if (null == ip4Address || "".equals(ip4Address)) {
                valiCode = "0004";
            } else {
                String localMacAddress = ServerNetInterfaceUtils.getServerMacAddress(ip4Address);
                if ("".equals(localMacAddress)) {
                    valiCode = "0005";  // 未在服务器上查找到IPv4地址与设置的授权IPv4地址一致的网卡
                } else if (!macAddress.equals(localMacAddress)){
                    valiCode = "0006";  // 设置的授权mac地址与当前安装系统的服务器mac地址不一致
                }
            }
        } else { // 获取证书其他验证信息失败
            valiCode = "0002";
        }
        return valiCode;
    }

    /**
     * 卸载证书 (开发环境)
     */
    public String uninstall() {
        String resultCode = "success";
        try {
            LicenseManager lm = this.getLicenseManager();
            lm.uninstall();
        } catch (Exception e) {
            resultCode = "2000";
            System.out.println("-------------------------------------- 证书错误，错误码：" + resultCode);
            e.printStackTrace();
        }
        return resultCode;
    }

    /**
     * 获取证书中, 对数据进行加密/解密的数据秘钥
     */
    public String getEncryptionKey() {
        String encodeKey,   // 秘钥的密文
               dataKeyPwd,  // 秘钥密文的解密密码
               dataKey = "";     // 秘钥
        String resultCode;
        String msg = "-------------------------------------- 证书错误，错误码：";
        try {
            LicenseContent content = this.getLicenseManager().verify(); // 验证证书的基本信息
            resultCode = this.validateExtraInfo(content);               // 验证证书的Mac地址信息
            Map extra = (Map)content.getExtra();
            encodeKey = (String) extra.get("DATA_KEY");
            dataKeyPwd = (String) extra.get("DATA_KEY_PWD");
            if (null != encodeKey && !"".equals(encodeKey)
                    && null != dataKeyPwd && !"".equals(dataKeyPwd)) {
                dataKey = XORUtil.getInstance().decode(encodeKey, dataKeyPwd);
            }
        } catch (NoLicenseInstalledException e) { // 没有安装证书
            resultCode = "1000";
        } catch (LicenseContentException e) {
            resultCode = "0000";
        } catch (Exception e) {
            resultCode = "0001";
            e.printStackTrace();
        }
        // 打印验证信息
        if (!"success".equals(resultCode)) {
            System.out.println(msg + resultCode);
        }
        return dataKey;
    }
}
